package com.gitee.simons.common.utils;

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @author JSM
 * @date 2018/11/20
 */
@Slf4j
public class JwtUtil {

	/**
	 *
	 */
	private static final String EXP = "exp";

	/**
	 *
	 */
	private static final String PAYLOAD = "payload";

	/**
	 * 加密生成token
	 * 
	 * @param object
	 *            载体信息
	 * @param maxAge
	 *            有效时长
	 * @param secret
	 *            服务器私钥
	 * @param <T>
	 * @return
	 */
	public static <T> String createToken(T object, long maxAge, String secret) {
		try {
			final JWTSigner signer = new JWTSigner(secret);
			final Map<String, Object> claims = new HashMap<String, Object>();
			ObjectMapper mapper = new ObjectMapper();
			String jsonString = mapper.writeValueAsString(object);
			claims.put(PAYLOAD, jsonString);
			claims.put(EXP, System.currentTimeMillis() + maxAge);
			return signer.sign(claims);
		} catch (Exception e) {
			log.error("生成token异常：", e);
			return null;
		}
	}

	/**
	 * 解析验证token
	 * 
	 * @param token
	 *            加密后的token字符串
	 * @param classT
	 *            解密后的对象类型
	 * @param secret
	 *            服务器私钥
	 * @return 如果token验证成功返回classT类型的对象，如果验证失败或过期返回null
	 */
	public static <T> T verifyToken(String token, Class<T> classT, String secret) {
		if (StringUtils.isBlank(token)) {
			return null;
		}
		final JWTVerifier verifier = new JWTVerifier(secret);
		try {
			final Map<String, Object> claims = verifier.verify(token);
			if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
				long exp = (Long) claims.get(EXP);
				long currentTimeMillis = System.currentTimeMillis();
				if (exp > currentTimeMillis) {
					String json = (String) claims.get(PAYLOAD);
					ObjectMapper objectMapper = new ObjectMapper();
					return objectMapper.readValue(json, classT);
				}
			}
			return null;
		} catch (Exception e) {
			log.error("验证token异常：", e);
			return null;
		}
	}

	/**
	 * 解析token(不作有效期判断)
	 * 
	 * @param token
	 *            加密后的token字符串
	 * @param classT
	 *            解密后的对象类型
	 * @param secret
	 *            服务器私钥
	 * @return 如果token验证成功返回classT类型的对象，如果验证失败或过期返回null
	 */
	public static <T> T parseToken(String token, Class<T> classT, String secret) {
		final JWTVerifier verifier = new JWTVerifier(secret);
		try {
			final Map<String, Object> claims = verifier.verify(token);
			if (claims.containsKey(PAYLOAD)) {
				String json = (String) claims.get(PAYLOAD);
				ObjectMapper objectMapper = new ObjectMapper();
				return objectMapper.readValue(json, classT);
			}
			return null;
		} catch (Exception e) {
			log.error("解析token异常：", e);
			return null;
		}
	}

}
